package cn.itrigger.dynamic.sql.select.render;

import cn.itrigger.dynamic.sql.where.render.WhereClauseProvider;
import static cn.itrigger.dynamic.sql.util.StringUtilities.*;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * @author admin
 * @date 2018/9/25
 **/
public class QueryExpression {
    private String tableName;
    private Optional<String> connector;
    private String columnList;
    private Optional<String> whereClause;
    private Map<String, Object> parameters;
    private boolean isDistinct;
    private Optional<String> joinClause;
    private Optional<String> groupByClause;

    private QueryExpression(Builder builder) {
        this.tableName = Objects.requireNonNull(builder.tableName);
        this.connector = Objects.requireNonNull(builder.connector);
        this.columnList = Objects.requireNonNull(builder.columnList);
        this.whereClause = Optional.of(builder.whereClause);
        this.parameters = Objects.requireNonNull(builder.parameters);
        this.isDistinct = builder.isDistinct;
        this.joinClause = Objects.requireNonNull(builder.joinClause);
        this.groupByClause = Objects.requireNonNull(builder.groupByClause);
    }

    public Map<String,Object> getParameters() {
        return parameters;
    }

    public String queryExpression() {
        return spaceAfter(connector)
                + "select "
                + (isDistinct ? "distinct " : "")
                + columnList
                + " from "
                + tableName
                + spaceBefore(joinClause)
                + spaceBefore(whereClause)
                + spaceBefore(groupByClause);
    }

    public static Builder withColumnList(String columnList) {
        return new Builder().withColumnList(columnList);
    }

    public static class Builder {
        private String tableName;
        private Optional<String> connector;
        private String columnList;
        private String whereClause;
        private Map<String, Object> parameters = new HashMap<>();
        private boolean isDistinct;
        private Optional<String> joinClause = Optional.empty();
        private Optional<String> groupByClause = Optional.empty();

        public Builder withConnector(Optional<String> connector) {
            this.connector = connector;
            return this;
        }

        public Builder withTableName(String tableName) {
            this.tableName = tableName;
            return this;
        }

        public Builder isDistinct(boolean isDistinct) {
            this.isDistinct = isDistinct;
            return this;
        }

        public Builder withWhereClause(Optional<WhereClauseProvider> whereClauseProvider) {
            whereClauseProvider.ifPresent(wcp -> {
                whereClause = wcp.getWhereClause();
                parameters.putAll(wcp.getParameters());
            });
            return this;
        }

        public Builder withColumnList(String columnList) {
            this.columnList = columnList;
            return this;
        }

        public Builder withJoinClause(Optional<String> joinClause) {
            this.joinClause = joinClause;
            return this;
        }

        public Builder withGroupByClause(Optional<String> groupByClause) {
            this.groupByClause = groupByClause;
            return this;
        }

        public QueryExpression build() {
            return new QueryExpression(this);
        }
    }
}
